package com.xinyin.aiqinhaiback.modbus;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.xinyin.aiqinhaiback.config.DeviceConfig;
import com.xinyin.aiqinhaiback.config.ModbusConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Slf4j
public class ModbusPoolManager {
	// 存储 IP -> 连接池 的映射
	private final Map<String, GenericObjectPool<ModbusMaster>> ipPoolMap;
	@Autowired
	public ModbusPoolManager(ModbusConfig modbusConfig) {
		this.ipPoolMap = new ConcurrentHashMap<>();
		// 根据配置初始化每个设备的连接池
		   for (Map.Entry<String, DeviceConfig> entry : modbusConfig.getDevices().entrySet()) {
			String deviceId = entry.getKey();
			DeviceConfig config = entry.getValue();
			initPool(deviceId,config.getIp(), config.getPort(), config.getMaxTotal(),config.getMaxIdle());
		}
	}



	/**
	 * 初始化指定 IP 的连接池
	 *
	 * @param ip       设备 IP 地址
	 * @param port     端口号
	 * @param maxTotal 最大连接数
	 * @param maxIdle  最大空闲连接数
	 */
	public void initPool(String name, String ip, int port, int maxTotal, int maxIdle) {
		if (ipPoolMap.containsKey(ip)) {
			return; // 已存在，跳过
		}

		// 配置池参数
		GenericObjectPoolConfig<ModbusMaster> config = new GenericObjectPoolConfig<>();
		config.setMaxTotal(maxTotal);
		config.setMaxIdle(maxIdle);
		config.setMinIdle(1);
		config.setMinEvictableIdleTimeMillis(60000); // 60秒回收

		// 创建 PooledObjectFactory
		BasePooledObjectFactory<ModbusMaster> factory = new BasePooledObjectFactory<ModbusMaster>() {
			@Override
			public ModbusMaster create() {

				try {
					System.out.println(ip + ":" + port + "连接正在创建");
					ModbusFactory modbusFactory = new ModbusFactory();
					IpParameters params = new IpParameters();
					params.setHost(ip);
					params.setPort(Integer.valueOf(port));
					ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false);
					tcpMaster.init();
					return tcpMaster;
				} catch (ModbusInitException e) {
					throw new RuntimeException("ip + \":\" + port + \"连接失败\"", e);
				}

			}


			@Override
			public void destroyObject(PooledObject<ModbusMaster> p) {
				System.out.println(ip+":"+port+"连接正在销毁");
				p.getObject().destroy();
			}

			@Override
			public boolean validateObject(PooledObject<ModbusMaster> p) {
				try {
					return p.getObject().isConnected();
				} catch (Exception e) {
					return false;
				}
			}

			@Override
			public PooledObject<ModbusMaster> wrap(ModbusMaster obj) {
				return new DefaultPooledObject<>(obj);
			}


		};

		// 创建并存储连接池
		GenericObjectPool<ModbusMaster> pool = new GenericObjectPool<>(factory, config);
		ipPoolMap.put(name, pool);
	}

	/**
	 * 获取指定 IP 的 Modbus 客户端
	 *
	 * @param name 设备 IP 地址
	 * @return ModbusTcpClient
	 * @throws Exception 获取失败时抛出异常
	 */
	public ModbusMaster getMaster(String name) throws Exception {
		GenericObjectPool<ModbusMaster> pool = ipPoolMap.get(name);
		if (pool == null) {
			throw new IllegalArgumentException("IP [" + name + "] 未初始化");
		}

		System.out.println("借出对象+"+name);
		return pool.borrowObject();
	}

	/**
	 * 归还客户端到对应 IP 的连接池
	 *
	 * @param name      设备 name
	 * @param master  ModbusTcpmaster 实例
	 */
	public void returnMaster(String name, ModbusMaster master) {
		GenericObjectPool<ModbusMaster> pool = ipPoolMap.get(name);

		if (pool != null) {
			// 前置日志
			log.info("Return connection before: Device={}, Active={}", name, pool.getNumActive());
			// 后置日志
			try {
				pool.returnObject(master);
				System.out.println("成功归还对象: 设备名=" + name );
				log.info("Return connection after: Device={}, Active={}", name, pool.getNumActive());
			} catch (Exception e) {
				log.error("Return connection failed: Device={}, Pool not found", name);
				System.err.println("归还对象失败: 设备名=" + name + ", 错误=" + e.getMessage());
				e.printStackTrace();
			}
		} else {
			System.err.println("归还对象失败: 设备名=" + name + ", 池不存在");
		}

	}

	/**
	 * 关闭所有连接池
	 */
	public void shutdownAll() {
		for (GenericObjectPool<ModbusMaster> pool : ipPoolMap.values()) {
			pool.close();
		}
		System.out.println("clearipPoolMap");
		ipPoolMap.clear();
	}
}
